<?php
class GroupsController extends AppController {
    var $name = 'Groups';
    
    function beforeFilter() {
        parent::beforeFilter(); 
        $this->Auth->allow('*');
    }
    
    function admin_index() {
        $this->paginate['Group'] = array(
            'order' => array('Group.created' => 'ASC'),
        );
        $groups = $this->paginate('Group');
        $this->set(compact('groups'));
    }
    
    function admin_add() {
        if(!empty($this->data)):
            if($this->Group->save($this->data)) :
                $this->admin_generate_aros();
                $this->Session->write('Success',true);
                $this->Session->setFlash('Group Saved');
                $this->redirect(array('controller' => 'groups','action'=>'index'));
                exit;
            endif;
        endif;
    }
    
    function admin_delete($id = null) {
        if($id == null) :
            $this->redirect($this->referer());
            exit;
        endif;
        $id = (int)$id;
        
        //prevent deleting superadmin
        if($id==1){
            $this->Session->setFlash('Superadmin is the primary group and is not allowed to be deleted!');
            $this->redirect($this->referer());
            exit;
        }
        $this->Group->User->unbindModel(array('belongsTo' => array('Group')));
        if($this->Group->delete($id)) :
            $this->Group->query('delete from aros where model="Group" and foreign_key='.$id);
            $this->Session->write('Success',true);
            $this->Session->setFlash('Group Deleted sucessfully');
        endif;
        $this->redirect($this->referer());
        exit;
    }
    
    function admin_build_acl() {
        /*
        if (!Configure::read('debug')) {
            return $this->_stop();
        }
        */
        $log = array();

        $aco =& $this->Acl->Aco;
        $root = $aco->node('controllers');
        if (!$root) {
            $aco->create(array('parent_id' => null, 'model' => null, 'alias' => 'controllers'));
            $root = $aco->save();
            $root['Aco']['id'] = $aco->id; 
            $log[] = 'Created Aco node for controllers';
        } else {
            $root = $root[0];
        }   

        App::import('Core', 'File');
        $Controllers = Configure::listObjects('controller');
        $appIndex = array_search('App', $Controllers);
        if ($appIndex !== false ) {
            unset($Controllers[$appIndex]);
        }
        $baseMethods = get_class_methods('Controller');
        $baseMethods[] = 'buildAcl';

        $Plugins = $this->_getPluginControllerNames();
        $Controllers = array_merge($Controllers, $Plugins);

        // look at each controller in app/controllers
        foreach ($Controllers as $ctrlName) {
            $methods = $this->_getClassMethods($this->_getPluginControllerPath($ctrlName));

            // Do all Plugins First
            if ($this->_isPlugin($ctrlName)){
                $pluginNode = $aco->node('controllers/'.$this->_getPluginName($ctrlName));
                if (!$pluginNode) {
                    $aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $this->_getPluginName($ctrlName)));
                    $pluginNode = $aco->save();
                    $pluginNode['Aco']['id'] = $aco->id;
                    $log[] = 'Created Aco node for ' . $this->_getPluginName($ctrlName) . ' Plugin';
                }
            }
            // find / make controller node
            $controllerNode = $aco->node('controllers/'.$ctrlName);
            if (!$controllerNode) {
                if ($this->_isPlugin($ctrlName)){
                    $pluginNode = $aco->node('controllers/' . $this->_getPluginName($ctrlName));
                    $aco->create(array('parent_id' => $pluginNode['0']['Aco']['id'], 'model' => null, 'alias' => $this->_getPluginControllerName($ctrlName)));
                    $controllerNode = $aco->save();
                    $controllerNode['Aco']['id'] = $aco->id;
                    $log[] = 'Created Aco node for ' . $this->_getPluginControllerName($ctrlName) . ' ' . $this->_getPluginName($ctrlName) . ' Plugin Controller';
                } else {
                    $aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $ctrlName));
                    $controllerNode = $aco->save();
                    $controllerNode['Aco']['id'] = $aco->id;
                    $log[] = 'Created Aco node for ' . $ctrlName;
                }
            } else {
                $controllerNode = $controllerNode[0];
            }

            //clean the methods. to remove those in Controller and private actions.
            foreach ($methods as $k => $method) {
                if (strpos($method, '_', 0) === 0) {
                    unset($methods[$k]);
                    continue;
                }
                if (in_array($method, $baseMethods)) {
                    unset($methods[$k]);
                    continue;
                }
                $methodNode = $aco->node('controllers/'.$ctrlName.'/'.$method);
                if (!$methodNode) {
                    $aco->create(array('parent_id' => $controllerNode['Aco']['id'], 'model' => null, 'alias' => $method));
                    $methodNode = $aco->save();
                    $log[] = 'Created Aco node for '. $method;
                }
            }
        }
        if(count($log)>0) {
            debug($log);
        }
    }

    function _getClassMethods($ctrlName = null) {
        App::import('Controller', $ctrlName);
        if (strlen(strstr($ctrlName, '.')) > 0) {
            // plugin's controller
            $num = strpos($ctrlName, '.');
            $ctrlName = substr($ctrlName, $num+1);
        }
        $ctrlclass = $ctrlName . 'Controller';
        $methods = get_class_methods($ctrlclass);

        // Add scaffold defaults if scaffolds are being used
        /*
        $properties = get_class_vars($ctrlclass);
        if (array_key_exists('scaffold',$properties)) {
            if($properties['scaffold'] == 'admin') {
                $methods = array_merge($methods, array('admin_add', 'admin_edit', 'admin_index', 'admin_view', 'admin_delete'));
            } else {
                $methods = array_merge($methods, array('add', 'edit', 'index', 'view', 'delete'));
            }
        }
        */
        return $methods;
    }

    function _isPlugin($ctrlName = null) {
        $arr = String::tokenize($ctrlName, '/');
        if (count($arr) > 1) {
            return true;
        } else {
            return false;
        }
    }

    function _getPluginControllerPath($ctrlName = null) {
        $arr = String::tokenize($ctrlName, '/');
        if (count($arr) == 2) {
            return $arr[0] . '.' . $arr[1];
        } else {
            return $arr[0];
        }
    }

    function _getPluginName($ctrlName = null) {
        $arr = String::tokenize($ctrlName, '/');
        if (count($arr) == 2) {
            return $arr[0];
        } else {
            return false;
        }
    }

    function _getPluginControllerName($ctrlName = null) {
        $arr = String::tokenize($ctrlName, '/');
        if (count($arr) == 2) {
            return $arr[1];
        } else {
            return false;
        }
    }

    /**
     * Get the names of the plugin controllers ...
     * 
     * This function will get an array of the plugin controller names, and
     * also makes sure the controllers are available for us to get the 
     * method names by doing an App::import for each plugin controller.
     *
     * @return array of plugin names.
     *
     */
    function _getPluginControllerNames() {
        App::import('Core', 'File', 'Folder');
        $paths = Configure::getInstance();
        $folder =& new Folder();
        $folder->cd(APP . 'plugins');

        // Get the list of plugins
        $Plugins = $folder->read();
        $Plugins = $Plugins[0];
        $arr = array();

        // Loop through the plugins
        foreach($Plugins as $pluginName) {
            // Change directory to the plugin
            $didCD = $folder->cd(APP . 'plugins'. DS . $pluginName . DS . 'controllers');
            // Get a list of the files that have a file name that ends
            // with controller.php
            $files = $folder->findRecursive('.*_controller\.php');

            // Loop through the controllers we found in the plugins directory
            foreach($files as $fileName) {
                // Get the base file name
                $file = basename($fileName);

                // Get the controller name
                $file = Inflector::camelize(substr($file, 0, strlen($file)-strlen('_controller.php')));
                if (!preg_match('/^'. Inflector::humanize($pluginName). 'App/', $file)) {
                    if (!App::import('Controller', $pluginName.'.'.$file)) {
                        debug('Error importing '.$file.' for plugin '.$pluginName);
                    } else {
                        /// Now prepend the Plugin name ...
                        // This is required to allow us to fetch the method names.
                        $arr[] = Inflector::humanize($pluginName) . "/" . $file;
                    }
                }
            }
        }
        return $arr;
    }
    
    function admin_generate_aros() {
        set_time_limit(0);
        $groups = $this->Group->find( 'list' );
        
        foreach( $groups as $group_id => $group_name ) {

            $group_aro = $this->Acl->Aro->findByForeignKeyAndModel( $group_id, 'Group' );
            //debug($group_aro);
            if( !isset( $group_aro['Aro']['id'] ) ) {
                $group_aro['Aro'] = array( 'parent_id'=>null, 'model'=>'Group', 'foreign_key'=>$group_id );
                $this->Acl->Aro->create();
                $this->Acl->Aro->save( $group_aro );
                $group_aro['Aro']['id'] = $this->Acl->Aro->getLastInsertId();
            }

            $users = $this->Group->User->find( 'list', array( 'conditions'=>'group_id = '.$group_id ) );
            
            foreach( $users as $user_id => $user_name ) {
                
                $user_aro = $this->Acl->Aro->findByForeignKeyAndModel( $user_id, 'User' );

                if( !isset( $user_aro['Aro']['id'] ) ) {
                    $user_aro['Aro'] = array( 'parent_id'=>$group_aro['Aro']['id'], 'model'=>'User', 'foreign_key'=>$user_id );
                    $this->Acl->Aro->create();
                    $this->Acl->Aro->save( $user_aro );
                }
            }
        }

    }
    
    


}
?>